﻿using Newtonsoft.Json;
using System;
using System.Linq;
using System.Reflection;

namespace Ycjw.PipeLine.Commons
{
    /// <summary>
    ///   动态库反射
    /// </summary>
    public class ReflectionHelper
    {
        /// <summary>
        /// 反射静态方法调用
        /// </summary>
        /// <param name="dllFileName">DLL的存放路径</param>
        /// <param name="className">类名</param>
        /// <param name="methodName">方法名</param>
        /// <param name="parameters">方法参数列表</param>
        /// <returns></returns>
        public static object GetStaticMethodObj(string dllFileName, string className, string methodName, object[] parameters)
        {
            Assembly assembly = Assembly.LoadFrom(dllFileName);
            if (assembly == null)
            {
                return null;
            }
            Type getType = assembly.GetType(className);
            if (getType == null)
            {
                return null;
            }
            MethodInfo methodInfo = getType.GetMethod(methodName);
            if (methodInfo == null)
            {
                return null;
            }
            return methodInfo.Invoke(null, parameters);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="dllFileName">DLL的存放路径</param>
        /// <param name="className">类名</param>
        /// <param name="singleName">单例名称</param>
        /// <param name="methodName">方法名</param>
        /// <param name="parameters">参数列表</param>
        /// <returns></returns>
        public static object GetSignleMethodObj(string dllFileName, string className, string singleName, string methodName, object[] parameters)
        {
            Assembly assembly = Assembly.LoadFrom(dllFileName);
            if (assembly == null)
            {
                return null;
            }
            Type type = assembly.GetType(className);
            if (type == null)
            {
                return null;
            }

            PropertyInfo info = type.GetProperty(singleName);
            if (info == null)
            {
                return null;
            }
            object obj = info.GetValue(null, null);
            if (obj == null)
            {
                return null;
            }
            return ExecutionMethod(obj, type, methodName, parameters);
        }

        /// <summary>
        /// 普通类反射调用方法
        /// </summary>
        /// <param name="dllFileName">库名</param>
        /// <param name="className">类名</param>
        /// <param name="methodName">方法名称</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        public static object GetComMethodObj(string dllFileName, string className, string methodName, object[] parameters)
        {
            Assembly assembly = Assembly.LoadFrom(dllFileName);
            if (assembly == null)
            {
                return null;
            }
            object obj = assembly.CreateInstance(className);
            if (obj == null)
            {
                return null;
            }
            Type type = obj.GetType();
            if (type == null)
            {
                return null;
            }
            return ExecutionMethod(obj, type, methodName, parameters);
        }

        /// <summary>
        /// 已知对象,执行相应的函数
        /// </summary>
        /// <param name="executionObj">执行对象</param>
        /// <param name="type">执行对象对应的类型</param>
        /// <param name="methodName">执行对象的需要执行的函数</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        public static object ExecutionMethod(object executionObj, Type type, string methodName, object[] parameters)
        {
            if (type == null)
            {
                return null;
            }
            //MethodInfo info = type.GetMethod.GetMethod(methodName);

            MethodInfo mathodGetAll = null;

            var mAll = type.GetMethods();
            var mInfos = mAll.Where(f => f.Name == methodName);
            if (mInfos.Count() == 1)
            {
                mathodGetAll = mInfos.First();
            }
            else
            {
                if (mAll != null && mAll.Any())
                {
                    mathodGetAll = mAll.FirstOrDefault(f => f.Name == methodName && f.GetParameters().Count() == parameters?.Count());
                }
            }

            if (mathodGetAll == null)
            {
                return null;
            }
            var temParameters = mathodGetAll.GetParameters();
            object[] objectParamList = null;
            Type[] typeArray;

            if (mathodGetAll.GetParameters().Length > 0)
            {
                if (parameters == null)
                {
                    parameters = new object[0];
                }
                typeArray = new Type[temParameters.Length];
                ParameterInfo[] infoArray3 = mathodGetAll.GetParameters();
                object[] objArray2 = new object[infoArray3.Length];
                for (int i = 0; i < infoArray3.Length; i++)
                {
                    if (i > parameters.Length - 1)
                    {
                        objArray2.SetValue(infoArray3[i].DefaultValue, i);
                    }
                    else if (parameters[i] == null)
                    {
                        objArray2.SetValue(parameters[i], i);
                    }
                    else
                    {
                        if (infoArray3[i].ParameterType.Name == "Object")
                        {
                            objArray2.SetValue(parameters[i], i);
                            typeArray.SetValue(infoArray3[i].ParameterType, i);
                        }
                        else
                        {
                            JsonSerializer serializer = new JsonSerializer();
                            string s = SerializeHelper.JsonHepler.Json_SerializeObject(parameters[i], true);
                            var temPtype = parameters[i].GetType();
                            object obj4 = serializer.Deserialize(new JsonTextReader(new System.IO.StringReader(s)), infoArray3[i].ParameterType.IsClass ? (infoArray3[i].ParameterType.Name == temPtype.Name ? infoArray3[i].ParameterType : temPtype) : infoArray3[i].ParameterType);
                            objArray2.SetValue(obj4, i);
                            if (obj4 != null)
                            {
                                typeArray.SetValue(infoArray3[i].ParameterType, i);
                            }
                        }
                    }
                }
                objectParamList = objArray2;
            }
            object infoDatas = null;
            try
            {
                return infoDatas = mathodGetAll.Invoke(executionObj, objectParamList);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                {
                    if (ex.InnerException.Message.Contains("System.ServiceModel.Channels.ServiceChannel"))
                    {
                        throw new Exception("WCF服务无法连接！", ex);
                    }
                    if (ex.InnerException.Message.Contains("Connection open error"))
                    {
                        throw new Exception("数据库连接失败！", ex);
                    }
                }
                LogHelper.Error(ex); return null;
            }
        }

        /// <summary>
        /// 创建类对象
        /// </summary>
        /// <param name="dllFileName">库名</param>
        /// <param name="className">类名</param>
        /// <returns></returns>
        public static object GetObjectFromDLL(string dllFileName, string className)
        {
            Assembly assembly = Assembly.LoadFrom(dllFileName);
            if (assembly == null)
            {
                return null;
            }
            return assembly.CreateInstance(className);
        }
    }
}